package com.skillworld.webapp.model.tutorial;

import java.sql.Time;
import java.util.Calendar;
import java.util.Locale;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import com.skillworld.webapp.model.department.Department;
import com.skillworld.webapp.model.user.User;

@Entity
@Table(name="Tutorial")
public class Tutorial {

    public enum Difficulty { EASY, MEDIUM, HARD }
	public enum Status { PENDING, REJECTED, ACCEPTED, VALIDATED }
	
	private Long tutorialId;
	private String title;
	private String summary;
	private Calendar creationDate;
	private Department department;
	private Difficulty difficulty;
	private int duration;
	private Locale language;
	private User author;
	private String xml;
	private Tutorial original;
	private Status status;
	private User validator = null;
	private Calendar validationDate = null;
	private String validationComment = null;
    private Double rating = null;
	private long points = 0;
	private long votes = 0;
	private long timesDone = 0;
	private long views = 0;
	

	protected Tutorial()
	{

	}

    public Tutorial(String title, String summary, Department department,
            Difficulty difficulty, int duration, Locale language, 
            User author, String xml) 
    {
        this.title = title;
        this.summary = summary;
        this.creationDate = Calendar.getInstance();
        this.department = department;
        this.difficulty = difficulty;
        this.duration = duration;
        this.language = language;
        this.author = author;
        this.xml = xml;
        this.original = null;
        this.status = Status.PENDING;
    }
	
	public Tutorial(String title, String summary, Department department,
	        Difficulty difficulty, int duration, Locale language, 
	        User author, String xml, Tutorial original) 
	{
        this.title = title;
        this.summary = summary;
        this.creationDate = Calendar.getInstance();
        this.department = department;
        this.difficulty = difficulty;
        this.duration = duration;
        this.language = language;
        this.author = author;
        this.xml = xml;
        this.original = original;
        this.status = Status.PENDING;
    }


    @SequenceGenerator(name="TutorialIdGenerator",sequenceName="TutorialSeq")
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO,generator="TutorialIdGenerator")
	@Column(name="idTutorial")
	public Long getTutorialId() {
		return tutorialId;
	}

	protected void setTutorialId(Long tutorialId) {
		this.tutorialId = tutorialId;
	}
	
    @Column(name="title")
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    @Column(name="summary")
    public String getSummary() {
        return summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }
    
    @Temporal(TemporalType.TIMESTAMP)
	@Column(name="creationDate")
	public Calendar getCreationDate() {
		return creationDate;
	}

	public void setCreationDate(Calendar creationDate) {
		this.creationDate = creationDate;
	}
	
    @ManyToOne(optional=false,fetch=FetchType.LAZY)
    @JoinColumn(name="idDepartment")
    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }
	
    @Enumerated(EnumType.STRING)
	@Column(name="difficulty")
	public Difficulty getDifficulty() {
		return difficulty;
	}

	public void setDifficulty(Difficulty difficulty) {
		this.difficulty = difficulty;
	}

	@Column(name="duration")
	public int getDuration()
	{ 
	    return duration; 
	}

	protected void setDuration(int duration)
	{ 
	    this.duration = duration; 
	}
	
    @Column(name = "lang")
    public Locale getLanguage() {
        return language;
    }

    public void setLanguage(Locale language) {
        this.language = language;
    }
    
    @ManyToOne(optional=false,fetch=FetchType.LAZY)
    @JoinColumn(name="idAuthor")
    public User getAuthor() {
        return author;
    }

    public void setAuthor(User author) {
        this.author = author;
    }

    @Column(name="contXML")
    public String getXml() {
        return xml;
    }

    public void setXml(String xml) {
        this.xml = xml;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="idOriginal")
    public Tutorial getOriginal() {
        return original;
    }

    public void setOriginal(Tutorial original) {
        this.original = original;
    }
    
    @Transient
    public boolean isDerived()
    {
        return original != null;
    }
    
    @Enumerated(EnumType.STRING)
	@Column(name="status")
	public Status getStatus() {
		return status;
	}

	protected void setStatus(Status status) {
		this.status = status;
	}
    
    @Transient
    public boolean isPending()
    { 
        return (status == Status.PENDING); 
    }
    
    @Transient
    public boolean isEvaluated()
    { 
        return (status != Status.PENDING); 
    }
    
    @Transient
    public boolean isRejected()
    { 
        return (status == Status.REJECTED); 
    }
    
    @Transient
    public boolean isAccepted()
    { 
        return (status == Status.ACCEPTED || status == Status.VALIDATED); 
    }
    
    @Transient
    public boolean isValidated()
    { 
        return (status == Status.VALIDATED); 
    }

    @ManyToOne(optional=true,fetch=FetchType.LAZY)
    @JoinColumn(name="idValidator")
    public User getValidator() {
        return validator;
    }

    protected void setValidator(User validator) {
        this.validator = validator;
    }
	
    @Column(name="validationDate")
    public Calendar getValidationDate() {
        return validationDate;
    }

    protected void setValidationDate(Calendar validationDate) {
        this.validationDate = validationDate;
    }
    
    @Column(name = "validationComment")
    public String getValidationComment() {
        return validationComment;
    }

    protected void setValidationComment(String comment) {
        this.validationComment = comment;
    }
    
    public void validate(User validator, Status status, String comment)
    {
        this.setStatus(status);
        this.setValidator(validator);
        this.setValidationDate(Calendar.getInstance());
        this.setValidationComment(comment);
    }
	
	@Column(name="rating")
	public Double getRating() {
		return rating;
	}

	protected void setRating(Double rating) {
		this.rating = rating;
	}

	@Column(name="points")
	public long getPoints() {
        return points;
    }

    protected void setPoints(long points) {
        this.points = points;
    }

    @Column(name="votes")
	public long getVotes()
    {
		return votes;
	}

	protected void setVotes(long votes) 
	{
		this.votes = votes;
	}
	
	@Column(name="timesDone")
	public long getTimesDone() 
	{
        return timesDone;
    }

    protected void setTimesDone(long timesDone)
    {
        this.timesDone = timesDone;
    }
    
    public void done()
    {
        timesDone++;
    }

    @Column(name="views")
	public long getViews() {
		return views;
	}

	protected void setViews(Long views) {
		this.views = views;
	}
	
	public void newView()
	{
	    views += 1;
	}
	
	public void rate(int rate)
	{
	    points += rate;
        votes += 1;
	    rating = ((double)points) / votes;
	}

}
